package cn.yx.framework.uploader;

import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.*;
import java.util.Iterator;
import java.util.List;

/**
 * @author ZHUL
 * @version V1.0
 * @Title: ${file_name}
 * @Package ${package_name}
 * @Description: ${todo}
 * @date 2017-03-03 11:13
 */
public class PluploadService {
    public static void upload(Plupload plupload, File pluploadDir) {
        //String fileName = "" + System.currentTimeMillis() + plupload.getName();//在服务器内生成唯一文件名
        //upload(plupload, pluploadDir, fileName);

        upload(plupload,
                pluploadDir,
                plupload.getId() + plupload.getName().substring(plupload.getName().lastIndexOf(".")));
    }

    private static void upload(Plupload plupload, File pluploadDir, String fileName) {

        int chunks = plupload.getChunks();//用户上传文件被分隔的总块数
        int nowChunk = plupload.getChunk();//当前块，从0开始

        //这里Request请求类型的强制转换可能出错，配置文件中向SpringIOC容器引入multipartResolver对象即可。
        MultipartHttpServletRequest multipartHttpServletRequest = (MultipartHttpServletRequest) plupload.getRequest();
        //调试发现map中只有一个键值对
        MultiValueMap map = multipartHttpServletRequest.getMultiFileMap();

        if (map != null) {
            try {
                Iterator iterator = map.keySet().iterator();
                while (iterator.hasNext()) {

                    String key = (String) iterator.next();
                    List multipartFileList = (List) map.get(key);

                    for (Object multipartFile : multipartFileList) {//循环只进行一次
                        MultipartFile multiFile = (MultipartFile) multipartFile;

                        plupload.setMultipartFile(multiFile);//手动向Plupload对象传入MultipartFile属性值
                        File targetFile = new File(pluploadDir + "/" + fileName);//新建目标文件，只有被流写入时才会真正存在
                        if (chunks > 1) {//用户上传资料总块数大于1，要进行合并

                            File tempFile = new File(pluploadDir.getPath() + "/" + multiFile.getName());
                            //第一块直接从头写入，不用从末端写入
                            savePluploadFile(multiFile.getInputStream(), tempFile, nowChunk == 0 ? false : true);

                            if (chunks - nowChunk == 1) {//全部块已经上传完毕，此时targetFile因为有被流写入而存在，要改文件名字
                                tempFile.renameTo(targetFile);
                            }
                        } else {
                            //只有一块，就直接拷贝文件内容
                            multiFile.transferTo(targetFile);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private static void savePluploadFile(InputStream inputStream, File tempFile, boolean flag) {
        OutputStream outputStream = null;
        try {
            if (flag == false) {
                //从头写入
                outputStream = new BufferedOutputStream(new FileOutputStream(tempFile));
            } else {
                //从末端写入
                outputStream = new BufferedOutputStream(new FileOutputStream(tempFile, true));
            }
            byte[] bytes = new byte[1024];
            int len = 0;
            while ((len = (inputStream.read(bytes))) > 0) {
                outputStream.write(bytes, 0, len);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
